package com.dingwen.stusprboomon.aspect;

import com.dingwen.stusprboomon.annotation.Check;
import com.dingwen.stusprboomon.util.CastUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

/**
 * 方法入参检查
 *
 * @author dingwen
 * 2021.06.28 10:14
 */
@Aspect
@Component
public class CheckAspect {

    /**
     * 定义切入点
     */
    @Pointcut("@annotation(com.dingwen.stusprboomon.annotation.Check)")
    public void check() {
    }


    /**
     * 环绕通知实现参数校验
     *
     * @param proceedingJoinPoint 进行连接点
     * @return {@link Object}
     */
    @Around("check()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) {
        try {
            // 获取拦截到的方法
            MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
            Method method = signature.getMethod();

            // 获取注解集合（二维数组）
            Annotation[][] parameterAnnotations = method.getParameterAnnotations();

            if (ObjectUtils.isEmpty(parameterAnnotations)) {
                return proceedingJoinPoint.proceed();
            }

            // 获取参数值
            Object[] paramValueArr = proceedingJoinPoint.getArgs();

            // 获取方法参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();


            for (int i = 0; i < parameterAnnotations.length; i++) {
                for (int j = 0; j < parameterAnnotations[i].length; j++) {
                    //如果该参数前面的注解不为空并且是Check的实例，并且参数不允许为空,并且默认值为空，则进行非空校验
                    if (!ObjectUtils.isEmpty(parameterAnnotations[i][j])
                            && parameterAnnotations[i][j] instanceof Check
                            && !((Check) parameterAnnotations[i][j]).allowEmpty()
                            && !StringUtils.hasText(((Check) parameterAnnotations[i][j]).defaultValue())) {
                        throw new RuntimeException("必传参数为空");
                    }
                    //如果该参数前面的注解不为空并且是ParamCheck的实例，并且默认值不为空，并且参数值为空，则进行赋默认值
                    if (!ObjectUtils.isEmpty(parameterAnnotations[i][j])
                            && parameterAnnotations[i][j] instanceof Check
                            && StringUtils.hasText(((Check) parameterAnnotations[i][j]).defaultValue())
                            && (ObjectUtils.isEmpty(paramValueArr[i]))) {

                        paramValueArr[i] = CastUtil.cast(parameterTypes[i].getSimpleName(),((Check) parameterAnnotations[i][j]).defaultValue());
                    }
                }
            }
            return proceedingJoinPoint.proceed();
        } catch (Exception exception) {
            //TODO 异常
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }
}
